package com.kolon.framework.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 날짜관련 속성을 얻는 클래스
 * @author stone
 *
 */
@SuppressWarnings("static-access")
public class DateUtil {
	ComUtil cut = new ComUtil();
	private static final int minYear = 1980;
	private static final int maxYear = 2100;
	
	/**
	 * Date 객체를 format에 맞게 변환
	 * @param Date
	 * @param String yyyyMMdd HHmmSS
	 * @return String
	 */
	public String getDateFormat(Date date, String format) {
		if (date == null) 
			throw new NullPointerException("날짜값이 NULL 입니다.");
		if (format == null || format.equals("")) 
			throw new IllegalArgumentException("잘못된 포멧정보입니다.");
		
		String dateStr = null;
		dateStr = new SimpleDateFormat(format).format(date);		
		return dateStr;
	}

	/**
	 * 년월일시분초밀리초를 합쳐서 16자리의 String으로 리턴하는 메소드
	 * @return String 년+월+일+시+분+초+밀리초(2자리만) 값
	 * <p><B>기타:</B>
	 * <ul>
	 * </ul>
	 */
	public String getDateTimeStr(){
		return getDateStr()+getTimeStr()+getMilliSecondStr();
	}

	public String getTimeStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.HOUR_OF_DAY), 2)+ComUtil.toZeroStr(cd.get(cd.MINUTE), 2)+ComUtil.toZeroStr(cd.get(cd.SECOND), 2);
	}

	/**
	 * 밀리초를 sss 형태로 리턴
	 * @return String - 밀리초(sss)
	 */
	
	public String getMilliSecondStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.MILLISECOND), 3);
	}

	/**
	 * 현재 yyyy-MM-dd 을 반환하는 함수 
	 */
	
	public static String getToday(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.YEAR), 4) + "-" + 
			ComUtil.toZeroStr(cd.get(cd.MONTH) + 1, 2) + "-" + 
			ComUtil.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
	}

	/**
	 * 년월일을 합쳐서 String으로 리턴하는 메소드
	 * @return String 년+월+일 값
	 */
	
	public static String getDateStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.YEAR), 4)+ComUtil.toZeroStr(cd.get(cd.MONTH) + 1, 2)+ComUtil.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
	}

	/**
	 * 년도를 YYYY 형태로 리턴
	 * @return String - 년도(YYYY)
	 */
	public static String getYearStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.YEAR), 4);
	}

	/**
	 * 월을 MM 형태로 리턴
	 * @return String - 월(MM)
	 */
	public static String getMonthStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.MONTH) + 1, 2);
	}

	/**
	 * 일을 DD 형태로 리턴
	 * @return String - 일(DD)
	 */
	public static String getDayStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
	}

	/**
	 * 시간을 HH 형태로 리턴
	 * @return String - 시간(HH)
	 */
	public static String getHourStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.HOUR_OF_DAY), 2);
	}

	/**
	 * 분을 mm 형태로 리턴
	 * @return String - 분(mm)
	 */
	public String getMinuteStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.MINUTE), 2);
	}

	/**
	 * 초를 ss 형태로 리턴
	 * @return String - 초(ss)
	 */
	public String getSecondStr(){
		Calendar cd = new GregorianCalendar(Locale.KOREA);
		return ComUtil.toZeroStr(cd.get(cd.SECOND), 2);
	}
	
	/**
	 * yyyyMMdd 형식의 문자열을 - 붙인후 반환하는 함수
	 * @param str	- 문자열
	 * @return
	 */
	public static String getFormatDate(String str){
		if(str == null || "".equals(str) || str.length() != 8){
			return "";
		}else{
			return str.substring(0, 4)+"-"+str.substring(4, 6)+"-"+str.substring(6, 8);
		}
	}

	/**
	 * 시작일부터 종료일까지 사이의 날짜를 MAP에 담아 리턴
	 * ( 시작일과 종료일을 모두 포함한다 )
	 * @param fromDate	- yyyyMMdd 형식의 시작일
	 * @param toDate	- yyyyMMdd 형식의 종료일
	 * @return			- yyyyMMdd 형식의 날짜가 담긴 배열
	 */
	public Map<String, String> getDiffDays(String fromDate, String toDate) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		Calendar cal = Calendar.getInstance();
		Map<String, String> map = new HashMap<String, String>();;
		try {
			cal.setTime(sdf.parse(fromDate));
		} catch (Exception e) {	}
		int count = getDiffDayCount(fromDate, toDate);
		cal.add(Calendar.DATE, -1);
		for (int i = 0; i <= count; i++) {
			cal.add(Calendar.DATE, 1);
			map.put(sdf.format(cal.getTime()), sdf.format(cal.getTime()));
		}
		return map;
	}

	/**
	 * 두날짜 사이의 일수를 리턴
	 * @param fromDate	- 시작일
	 * @param toDate	- 종료일
	 * @return
	 */
	public int getDiffDayCount(String fromDate, String toDate){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		try{
			return (int)((sdf.parse(toDate).getTime() - sdf.parse(fromDate).getTime()) / 1000 / 60 / 60 /24);
		}catch (Exception e){
			return 0;
		}
	}
	
	/**
	 * 해당 년월의 최대 날 수를 반환
	 * @param year
	 * @param month
	 * @return lastDay
	 */
	public static int getLastDay(String year, String month) {
		if (year == null || year.equals("")
				|| month == null || month.equals("")) {
			throw new IllegalArgumentException("잘못된 년/월 정보입니다.");
		}
		
		int nYear = Integer.parseInt(year);
		int nMonth = Integer.parseInt(month);
		
		return getLastDay(nYear, nMonth);
	}
	
	/**
	 * 해당 년월의 최대 날 수를 반환
	 * @param year
	 * @param month
	 * @return
	 */
	public static int getLastDay(int year, int month) {
		Calendar cal = Calendar.getInstance();
		
		if (!isAvailableYear(year)) {
			year = cal.get(Calendar.YEAR);
		}
		
		if (!isAvailableMonth(month)) {
			month = cal.get(Calendar.MONTH) + 1;
		}
		
		cal.set(year, month - 1, 1);
		
		int lastDay = cal.getActualMaximum(Calendar.DATE);
		
		return lastDay;
	}
	
	/**
	 * 년정보가 정의된 범위 안에서 유효한지를 체크
	 * @param year
	 * @return
	 */
	public static boolean isAvailableYear(int year) {

		if (year < minYear || year > maxYear) {
			return false;
		}
		
		return true;
	}
	
	/**
	 * 월정보가 정의된 범위 안에서 유효한지를 체크
	 * @param month
	 * @return
	 */
	public static boolean isAvailableMonth(int month) {

		if (month < 1 || month > 12) {
			return false;
		}
		
		return true;
	}
	
	/**
	 * 특정날짜의 요일을 얻는 함수
	 */
	public  String getDayWeek(int year, int month, int day){
		String[] dayOfWeek={"일","월","화","수","목","금","토"};
		
		Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month-1);
        cal.set(Calendar.DAY_OF_MONTH, day);
		
		int week = cal.get(Calendar.DAY_OF_WEEK);
		return dayOfWeek[week-1];
	}
	
	/**
	 * 특정날짜의 더해진 년월일을 얻는 함수(주말일시 다음날날짜)
	 */
	public  String getCalDateStr(String sYearPara, String sMonthPara, String sDayPara, int iTerm, String sGuBun){
		  Calendar cd = new GregorianCalendar(Integer.parseInt(sYearPara),Integer.parseInt(sMonthPara)-1,Integer.parseInt(sDayPara));
		  String sYear  = null;
		  String sMonth = null;
		  String sDay   = null;
		  if( cut.stringCompare(sGuBun, "day") )
		  {
			 cd.add( cd.DATE, iTerm );
			 sYear  = cut.toZeroStr(cd.get(cd.YEAR), 4);
			 sMonth = cut.toZeroStr(cd.get(cd.MONTH)+1, 2);
			 sDay   = cut.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
		  }
		  else if( cut.stringCompare(sGuBun, "month") )
		  {
			 cd.add( cd.MONTH, iTerm );
			 sYear  = cut.toZeroStr(cd.get(cd.YEAR), 4);
			 sMonth = cut.toZeroStr(cd.get(cd.MONTH)+1, 2);
			 sDay   = cut.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
		  }
		  else if( cut.stringCompare(sGuBun, "year") )
		  {
			 cd.add( cd.YEAR, iTerm );
			 sYear  = cut.toZeroStr(cd.get(cd.YEAR), 4);
			 sMonth = cut.toZeroStr(cd.get(cd.MONTH)+1, 2);
			 sDay   = cut.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
		  }
		  String week = getDayWeek(Integer.parseInt(sYear), 
				  Integer.parseInt(sMonth), Integer.parseInt(sDay));
		  if ("토".equals(week) || "일".equals(week)) {
			  return getCalDateStr(sYearPara, sMonthPara, sDayPara, iTerm+1, "day");
		  }
		  String week_ = getDayWeek(Integer.parseInt(sYearPara), 
				  Integer.parseInt(sMonthPara), Integer.parseInt(sDayPara));
		  if ("목".equals(week_)) {
			  return getCalDateStr_(sYear, sMonth, sDay, 1, "day");
		  } else if ("금".equals(week_)) {
			  return getCalDateStr_(sYear, sMonth, sDay, 2, "day");
		  } else if ("토".equals(week_)) {
			  return getCalDateStr_(sYear, sMonth, sDay, 1, "day");
		  }
		  return sYear+sMonth+sDay;
	}
	
	/**
	 * 특정날짜의 더해진 년월일을 얻는 함수
	 */
	public  String getCalDateStr_(String sYearPara, String sMonthPara, String sDayPara, int iTerm, String sGuBun){
		  Calendar cd = new GregorianCalendar(Integer.parseInt(sYearPara),Integer.parseInt(sMonthPara)-1,Integer.parseInt(sDayPara));
		  String sYear  = null;
		  String sMonth = null;
		  String sDay   = null;
		  if( cut.stringCompare(sGuBun, "day") )
		  {
			 cd.add( cd.DATE, iTerm );
			 sYear  = cut.toZeroStr(cd.get(cd.YEAR), 4);
			 sMonth = cut.toZeroStr(cd.get(cd.MONTH)+1, 2);
			 sDay   = cut.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
		  }
		  else if( cut.stringCompare(sGuBun, "month") )
		  {
			 cd.add( cd.MONTH, iTerm );
			 sYear  = cut.toZeroStr(cd.get(cd.YEAR), 4);
			 sMonth = cut.toZeroStr(cd.get(cd.MONTH)+1, 2);
			 sDay   = cut.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
		  }
		  else if( cut.stringCompare(sGuBun, "year") )
		  {
			 cd.add( cd.YEAR, iTerm );
			 sYear  = cut.toZeroStr(cd.get(cd.YEAR), 4);
			 sMonth = cut.toZeroStr(cd.get(cd.MONTH)+1, 2);
			 sDay   = cut.toZeroStr(cd.get(cd.DAY_OF_MONTH), 2);
		  }
		  return sYear+sMonth+sDay;
	}
}
